#include "Game.h"

Game::Game(RenderWindow &app) : app(app), 
                                camera(app), 
                                cursor(app), 
                                map(units) {

    width = app.GetWidth();
    height = app.GetHeight();
    font.LoadFromFile("data/lazy.ttf");
    actionMode.SetFont(font);
    actionMode.SetSize(42);
    actionMode.Move(500.f,500.f);

    selectedUnit = NULL;
    units.push_back(new Knight(map, 4, 4));
    units.push_back(new Knight(map, 3, 4));
    actionType = ACT_MOVE;
    actionMode.SetText("move mode");

    map.Load("data/map.txt");
    map.PopulateTiles();

    Image *image = new Image();
    image->LoadFromFile("gfx/overlays.png");
    
    tileOverlay.SetImage(*image);
    tileOverlay.SetSubRect(IntRect(0, 0, 64, 64));

    moveOverlay.SetImage(*image);
    moveOverlay.SetSubRect(IntRect(64, 0, 128, 64));
    //moveOverlay.SetBlendMode(Blend::Add);
    
    attackOverlay.SetImage(*image);
    attackOverlay.SetSubRect(IntRect(128, 0, 192, 64));

    rotateOverlay.SetImage(*image);
    rotateOverlay.SetSubRect(IntRect(193, 0 , 256, 64));
    rotateOverlay.SetCenter(32, 32);
}

Game::~Game() {
}

void Game::HandleEvent(Event &event) {
    if (event.Type == Event::MouseMoved) {
        // pass mouse movement to cursor
        cursor.HandleMouseEvent(event);
    }
    else if (event.Type == Event::LostFocus) {
        // disable cursor centering
        cursor.Disable();
    }
    else if (event.Type == Event::GainedFocus) {
        // renable cursor centering
        cursor.Enable();
    }
    else if (event.Type == Event::MouseWheelMoved) {
        // zoom camera
        camera.Zoom(event.MouseWheel.Delta*0.1f);
    }    
    else if (event.Type == Event::MouseButtonPressed) {
        if (event.MouseButton.Button == Mouse::Left) {
            Vector2i cursorPos = cursor.GetPos();
            Vector2f pos = app.ConvertCoords(cursorPos.x,
                                             cursorPos.y,
                                             &camera.GetView());
            Vector2i tilePos(pos.x/TILE_SIZE, pos.y/TILE_SIZE);
            bool action = false;
            for (int i=0; i<currMoves.size(); i++) {
                if (currMoves[i] == tilePos) {
                    selectedUnit->DoAction(actionType, tilePos.x, tilePos.y);
                    map.PopulateTiles();
                    currMoves = selectedUnit->GetActions(actionType);
                    action = true;
                    break;
                }
            }

            if (action == false) {
                Tile *tile = map.GetTile(pos.x/TILE_SIZE, pos.y/TILE_SIZE);
                if (tile == NULL || tile->unit == NULL) {
                    selectedUnit = NULL;
                    currMoves.clear();
                }
                else {
                    selectedUnit = tile->unit;
                    currMoves = selectedUnit->GetActions(actionType);
                }
            }
        }
        else if (event.MouseButton.Button == Mouse::Right) {
            selectedUnit = NULL;
            currMoves.clear();
        }
    }
    else if (event.Type == Event::KeyPressed) {
        /*if (event.Key.Code == Key::A) {
            if (selectedUnit != NULL) {
                selectedUnit->RotateCCW();
                currMoves = selectedUnit->GetActions(actionType);
            }
        }
        else if (event.Key.Code == Key::D) {
            if (selectedUnit != NULL) {
                selectedUnit->RotateCW();
                currMoves = selectedUnit->GetActions(actionType);
            }
        }*/
        if (event.Key.Code == Key::Num1) {
            actionType = ACT_MOVE;
            actionMode.SetText("move mode");
            if (selectedUnit != NULL) {
                currMoves = selectedUnit->GetActions(actionType);
            }
        }
        else if (event.Key.Code == Key::Num2) {
            actionType = ACT_ATTACK;
            actionMode.SetText("attack mode");
            if (selectedUnit != NULL) {
                currMoves = selectedUnit->GetActions(actionType);
            }
        }
        else if (event.Key.Code == Key::Num3) { 
            actionType = ACT_ROTATE;
            actionMode.SetText("rotate mode");
            if (selectedUnit != NULL) { 
                currMoves = selectedUnit->GetActions(actionType);
            }
        }
        else if (event.Key.Code == Key::Escape) {
            app.Close();
        }
    }
}

void Game::Init() {
}

void Game::End() {
    map.UnLoad();
}

void Game::Update(float dt) {
    // move camera if cursor is near edge
    Vector2i &mousePos = cursor.GetPos();
    if (mousePos.x < 10) {
        camera.MoveTarget(-400*dt, 0);
    }
    else if (mousePos.x > width-10) {
        camera.MoveTarget(400*dt, 0);
    }
    if (mousePos.y < 10) {
        camera.MoveTarget(0, -400*dt);
    }
    else if (mousePos.y > height-10) {
        camera.MoveTarget(0, 400*dt);
    }
    
    // update tile overlay
    Vector2i cursorPos = cursor.GetPos();
    Vector2f pos = app.ConvertCoords(cursorPos.x,
                                     cursorPos.y,
                                     &camera.GetView());
    Vector2i tilePos(pos.x/TILE_SIZE, pos.y/TILE_SIZE);
    Tile *tile = map.GetTile(tilePos.x, tilePos.y);
    if (tile != NULL) {
        tilePos *= TILE_SIZE;
        tileOverlay.SetPosition(tilePos.x, tilePos.y);
        tileOverlay.SetColor(Color(255, 255, 255, 255));
    }
    else {
        tileOverlay.SetColor(Color(0, 0, 0, 0));
    }

    // update everything
    cursor.Update(dt);
    camera.Update(dt);
    map.Update(dt);
}

void Game::Render(RenderWindow &app) {
    // render game view stuff
    app.SetView(camera.GetView());
    map.Render(spriteManager);

    // render tile overlay
    spriteManager.Draw(tileOverlay);

    // render movement overlays
     
    for (int i=0; i<currMoves.size(); i++) {
        int x = currMoves[i].x*TILE_SIZE;
        int y = currMoves[i].y*TILE_SIZE;
        if (actionType == ACT_MOVE) {
            moveOverlay.SetPosition(x, y);
            spriteManager.Draw(moveOverlay);
        }
        else if (actionType == ACT_ATTACK) {
            attackOverlay.SetPosition(x, y);
            spriteManager.Draw(attackOverlay);
        }
        else if (actionType == ACT_ROTATE) {
            rotateOverlay.SetRotation(-45*i);
            rotateOverlay.SetPosition(x+32, y+32);
            spriteManager.Draw(rotateOverlay);
        }
    }

    // render units
    for (int i=0; i<units.size(); i++) {
        units[i]->Render(spriteManager);
    }

    spriteManager.Render(app);

    // render user interface stuff
    app.SetView(app.GetDefaultView());
    cursor.Render(app);
    app.Draw(actionMode);
}

